package cn.bjit.service.impl;

import cn.bjit.config.RabbitMQConfig;
import cn.bjit.enums.BizCodeEnum;
import cn.bjit.enums.ProductOrderStateEnum;
import cn.bjit.enums.StockTaskStateEnum;
import cn.bjit.exception.BizException;
import cn.bjit.feign.ProductOrderFeignService;
import cn.bjit.mapper.ProductMapper;
import cn.bjit.mapper.ProductTaskMapper;
import cn.bjit.model.ProductDO;
import cn.bjit.model.ProductMessage;
import cn.bjit.model.ProductTaskDO;
import cn.bjit.request.LockProductRequest;
import cn.bjit.request.OrderItemRequest;
import cn.bjit.service.ProductService;
import cn.bjit.util.JsonData;
import cn.bjit.vo.ProductVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ProductServiceImpl implements ProductService {
    @Resource
    private ProductMapper productMapper;

    @Resource
    private ProductTaskMapper productTaskMapper;


    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private RabbitMQConfig rabbitMQConfig;
    @Resource
    private ProductOrderFeignService productOrderFeignService;

    /**
     * 分页查询商品列表
     *
     * @param page
     * @param size
     * @return
     */
    public Map<String, Object> page(int page, int size) {
        Page pageInfo = new Page<>(page, size);
        IPage<ProductDO> productDOIPage = productMapper.selectPage(pageInfo, null);//SELECT *

        Map<String, Object> pageMap = new HashMap<>(3);
        pageMap.put("total_record", productDOIPage.getTotal());
        pageMap.put("total_page", productDOIPage.getPages());
        pageMap.put("current_data", productDOIPage.getRecords().stream().map(obj -> beanProcess(obj)).collect(Collectors.toList()));

        return pageMap;
    }

    //根据id查看详细信息
    public ProductVO findDetailById(long productId) {
        ProductDO productDO = productMapper.selectById(productId);
        return beanProcess(productDO);
    }

    //批量查询
    @Override
    public List<ProductVO> findProductByIdBatch(List<Long> productIdList) {
        List<ProductDO> productDOList = productMapper.selectList(new QueryWrapper<ProductDO>().in("id", productIdList));
        List<ProductVO> productVOList = productDOList.stream().map(obj -> beanProcess(obj)).collect(Collectors.toList());
        return productVOList;
    }

    /**
     * 商品库存锁定
     *
     * @param lockProductRequest
     * @return
     */
    public JsonData lockProductStock(LockProductRequest lockProductRequest) {
        //1,获取订单
        String orderOutTradeNo = lockProductRequest.getOrderOutTradeNo();
        //2,获取订单项
        List<OrderItemRequest> orderItemList = lockProductRequest.getOrderItemList();
        //3，获取每个商品子项id
        List<Long> productIdList = orderItemList.stream().map(OrderItemRequest::getProductId).collect(Collectors.toList());
        //4，批量查询
        List<ProductVO> productVOList = this.findProductByIdBatch(productIdList);
        //5,分组
        Map<Long, ProductVO> productMap = productVOList.stream().collect(Collectors.toMap(ProductVO::getId, Function.identity()));

        for (OrderItemRequest item : orderItemList) {
            //锁定商品记录,操作的是product这张表
            int rows = productMapper.lockProductStock(item.getProductId(), item.getBuyNum());
            if (rows != 1) {
                throw new BizException(BizCodeEnum.ORDER_CONFIRM_LOCK_PRODUCT_FAIL);
            } else {
                //插入商品锁定库存表 product_task中
                ProductVO productVO = productMap.get(item.getProductId());
                ProductTaskDO productTaskDO = new ProductTaskDO();
                productTaskDO.setBuyNum(item.getBuyNum());
                productTaskDO.setLockState(StockTaskStateEnum.LOCK.name());
                productTaskDO.setProductId(item.getProductId());
                productTaskDO.setProductName(productVO.getTitle());
                productTaskDO.setOutTradeNo(orderOutTradeNo);
                //插入到product_task表中
                productTaskMapper.insert(productTaskDO);

                // 发送MQ延迟消息，释放商品库存
                ProductMessage  productMessage=new ProductMessage();
                productMessage.setTaskId(productTaskDO.getId());
                productMessage.setOutTradeNo(productTaskDO.getOutTradeNo());
                rabbitTemplate.convertAndSend(rabbitMQConfig.getEventExchange(),rabbitMQConfig.getStockReleaseDelayRoutingKey(),productMessage);
                    log.info("消息返送成功{}",productMessage);
            }

        }
        return JsonData.buildSuccess();
    }

    /**
     * 释放商品库存
     * @param productMessage
     * @return
     */
    public boolean releaseProductStock(ProductMessage productMessage) {
        ProductTaskDO productTaskDO=productTaskMapper.selectOne(new QueryWrapper<ProductTaskDO>().eq("id",productMessage.getTaskId()));
        if(productTaskDO==null){
               log.warn("工作单不 存在，消息是：{}",productMessage);
        }
        if(productTaskDO.getLockState().equalsIgnoreCase(StockTaskStateEnum.LOCK.name())){
           JsonData jsonData= productOrderFeignService.queryProductOrderState(productMessage.getOutTradeNo());
           if(jsonData.getCode()==0){
                String state= jsonData.getData().toString(); //PAY,CANCEL,    NEW,
               //1，如果是NEW
                if(ProductOrderStateEnum.NEW.name().equalsIgnoreCase(state)){
                   log.info("订单是NEW转态，则返回消息队列，让重新投递{}",productMessage);
                   return false;
                }
                //2，如果是PAY  则修改字段为finish
               if(ProductOrderStateEnum.PAY.name().equalsIgnoreCase(state)){
                   productTaskDO.setLockState(StockTaskStateEnum.FINISH.name());
                   productTaskMapper.update(productTaskDO,new QueryWrapper<ProductTaskDO>().eq("id",productMessage.getTaskId()));
                   log.info("订单已经支付,修改Lock为FINISH,消息是{}",productMessage);
                   return true;
               }
           }
           //3，订单不存在
            log.info("订单不存在，或者订单被取消，确认消息，把task修改为CANCEL,库存回复，{}",productMessage);
            productTaskDO.setLockState(StockTaskStateEnum.CANCEL.name());
            productTaskMapper.update(productTaskDO,new QueryWrapper<ProductTaskDO>().eq("id",productMessage.getTaskId()));

            //恢复库存，就是锁定库存的值-购买的值
            productMapper.unLockProductStock(productTaskDO.getProductId(),productTaskDO.getBuyNum());
            return true;
        }else{
           log.warn("工作单不是lock状态，消息{}",productMessage);
           return true;
        }
    }

    private ProductVO beanProcess(ProductDO productDO) {
        ProductVO productVO = new ProductVO();
        BeanUtils.copyProperties(productDO, productVO);
        //假设数据库中有100个库存，但是有10个处于支付状态，这时候这10个就处于锁定状态，则显示给用户的库存就应该是
        //100-10=90;
        productVO.setStock(productDO.getStock() - productDO.getLockStock());
        return productVO;
    }
}
